//
//  TcpClient.swift
//  pluto
//
//  Created by andyge on 15/7/28.
//  Copyright © 2015年 gejingguo. All rights reserved.
//

import Foundation


// 网络数据
public class TcpData {
    static let DATA_SIZE = 1024
    var data: UnsafeMutablePointer<CChar>? = nil
    var read = 0
    var write = 0
    var capacity = 0
    
    init(count: Int = 0) {
        if count <= 0 {
            capacity = TcpData.DATA_SIZE
        } else {
            capacity = count
        }
        
        data = UnsafeMutablePointer<CChar>.alloc(capacity)
        data?.initialize(0)
        //print("tcpdata init.")
    }
    
    deinit {
        if data != nil {
            data?.destroy()
            data?.dealloc(capacity)
        }
    }
    
    public func clear() {
        self.read = 0
        self.write = 0
    }
    
    public var space: Int {
        if write >= (capacity - 1) {
            return 0
        }
        return capacity - 1 - write
    }
    
    public var size: Int {
        return write - read
    }
    
    public var writeAddr: UnsafeMutablePointer<CChar> {
        return (data?.advancedBy(write))!
    }
    
    public var readAddr: UnsafeMutablePointer<CChar> {
        return (data?.advancedBy(read))!
    }
    
}

/// TCP客户端连接类
public class TcpClient: PollObject {
    public var id: Int = 0
    public var fd: Int32? = nil
    public var serverAddr: String? = nil
    var tcpServer: TcpServer? = nil
    public var recvBuf = TcpData()
    public var sendBuf = TcpData()
    var poller: Poller? = nil
    
    /// 接受的新连接对象构造函数
    init(poller: Poller, fd: Int32, serverAddr: String, server: TcpServer) {
        self.fd = fd
        self.serverAddr = serverAddr
        self.poller = poller
        self.tcpServer = server
        //self.protoDelegate = protoDelegate
        print("tcpclient init.")
    }
    
    /// 默认构造函数, 方便后续connect
    init() {
        
    }
    
    deinit {
        print("tcpclient deinit..")
        if fd != nil {
            close(fd!)
            fd = nil
        }
    }
    
    /// 连接有效性
    var isValid: Bool {
        get {
            return (self.fd != nil && self.fd >= 0)
        }
    }
    
    /// 连接服务器，建立新连接
    func connect(serverAddr: String, port: Int) -> Error? {
        return nil
    }
    
    /// 接收网络数据，读到缓存中
    func recv() -> Error? {
        if self.fd == nil {
            
        }
        
        if recvBuf.space <= 0 {
            print("buf space 0")
            return nil
        }
        
        let ret = Darwin.recv(fd!, recvBuf.writeAddr, recvBuf.space, Int32(0))
        if ret < 0 {
            if errno == EWOULDBLOCK || errno == EAGAIN {
                print("recv egain")
                return nil
            }
            return TcpError(err: TcpErrorNo.TcpErrorNo_SocketRead.rawValue)
        }
        else if ret == 0 {
            return TcpError(err: TcpErrorNo.TcpErrorNo_SocketClosedByPeer.rawValue, msg: "closed by peer")
        }
        
        recvBuf.write += ret
        
        let recvData = String.fromCString(recvBuf.readAddr)
        print("recv data : \(recvData)")
        
        return nil
    }
    
    /// 发送数据, 将数据拷贝到发送缓存中
    public func send(data: UnsafeMutablePointer<CChar>, size: Int) -> Error? {
        if size <= 0 {
            return nil
        }
        
        if sendBuf.space < size {
            return TcpError(err: TcpErrorNo.TcpErrorNo_SendBufNotEnough.rawValue, msg: "tcpclient sendbuf space not enough")
        }
        
        // 原来数据为空的话，更新可写事件
        if self.poller != nil && self.sendBuf.size == 0 {
            var po: PollObject = self
            self.poller?.updatePollObject(&po, write: true)
        }
        
        Darwin.memcpy(self.sendBuf.writeAddr, data, size)
        self.sendBuf.write += size
        
        return nil
    }
    
    /// 发送缓存中数据
    func send() -> Error? {
        if sendBuf.size <= 0 {
            return nil
        }
        
        let ret = Darwin.send(fd!, sendBuf.readAddr, sendBuf.size, Int32(0))
        if ret < 0 {
            if errno == EWOULDBLOCK || errno == EAGAIN {
                print("send egain")
                return nil
            }
            return TcpError(err: TcpErrorNo.TcpErrorNo_SocketSend.rawValue)
        }
        
        sendBuf.read += ret
        print("send data size:\(ret)")
    
        
        if sendBuf.read == sendBuf.write {
            sendBuf.read = 0
            sendBuf.write = 0
            if self.poller != nil {
                var po: PollObject = self
                self.poller?.updatePollObject(&po, write: false)
            }
        }
    
        return nil
    }
    
    public func onRead(poller: Poller) -> Error? {
        let oldWrite = self.recvBuf.write
        
        let err = self.recv()
        if err != nil {
            return err
        }
        
        if oldWrite != self.recvBuf.write && poller.tcpDelegate != nil {
            let ret = poller.tcpDelegate!.onTcpClientRead(self)
            if ret  > 0 {
                self.recvBuf.read += ret
                if self.recvBuf.read == self.recvBuf.write {
                    self.recvBuf.read = 0
                    self.recvBuf.write = 0
                }
            }
        }
        
        return nil
    }
    
    public func onWrite(poller: Poller) -> Error? {
        return self.send()
    }
    
    public func onError(poller: Poller, err: Error) {
        poller.tcpDelegate?.onTcpClientError(self, err: err)
    }

}